package timing.ukulele.auth.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import timing.ukulele.auth.config.properties.TimingSecurityProperties;
import timing.ukulele.auth.security.handler.LoginFailureHandler;
import timing.ukulele.auth.security.handler.LoginSuccessHandler;
import timing.ukulele.auth.security.handler.UkuleleLogoutSuccessHandler;
import timing.ukulele.auth.security.type.image.ImageCodeAuthenticationSecurityConfig;
import timing.ukulele.auth.security.type.sms.SmsCodeAuthenticationSecurityConfig;
import timing.ukulele.auth.security.type.wechat.ThirdQrAuthenticationSecurityConfig;
import timing.ukulele.auth.security.user.TimingUserDetailService;
import timing.ukulele.auth.security.user.UnionUserDetailService;
import timing.ukulele.auth.support.RedisOperator;

/**
 * 将bean注入至ioc的配置类
 */
@Configuration
@EnableConfigurationProperties
public class BeanConfig {
    private final UnionUserDetailService thirdPartyUserService;
    private final RedisOperator<String> stringRedisOperator;

    public BeanConfig(UnionUserDetailService thirdPartyUserService,
                      RedisOperator<String> stringRedisOperator) {
        this.thirdPartyUserService = thirdPartyUserService;
        this.stringRedisOperator = stringRedisOperator;

    }

    /**
     * 跨域过滤器配置
     *
     * @return CorsFilter
     */
    @Bean
    public CorsFilter corsFilter() {

        // 初始化cors配置对象
        CorsConfiguration configuration = new CorsConfiguration();

        // 设置允许跨域的域名,如果允许携带cookie的话,路径就不能写*号, *表示所有的域名都可以跨域访问
//        configuration.addAllowedOrigin("http://www.ukulele.com:4200");// 设置跨域访问可以携带cookie
//        configuration.setAllowCredentials(true);

        configuration.addAllowedOrigin("*");
        configuration.setAllowCredentials(false);
        // 允许所有的请求方法 ==> GET POST PUT Delete
        configuration.addAllowedMethod("*");
        // 允许携带任何头信息
        configuration.addAllowedHeader("*");

        // 初始化cors配置源对象
        UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();

        // 给配置源对象设置过滤的参数
        // 参数一: 过滤的路径 == > 所有的路径都要求校验是否跨域
        // 参数二: 配置类
        configurationSource.registerCorsConfiguration("/**", configuration);

        // 返回配置好的过滤器
        return new CorsFilter(configurationSource);
    }

//    @Bean
//    public HttpSessionSecurityContextRepository securityContextRepository(){
//        return new HttpSessionSecurityContextRepository();
//    }

    @Bean
    public LoginSuccessHandler loginSuccessHandler(RedisOperator<String> redisOperator,
                                                   JwtEncoder jwtEncoder,
                                                   TimingSecurityProperties securityProperties) {
        return new LoginSuccessHandler(redisOperator, jwtEncoder, securityProperties);
    }

    @Bean
    public LoginFailureHandler loginFailureHandler() {
        return new LoginFailureHandler();
    }

    @Bean
    public UkuleleLogoutSuccessHandler logoutSuccessHandler(RedisOperator<String> redisOperator,
                                                            JwtDecoder jwtDecoder) {
        return new UkuleleLogoutSuccessHandler(jwtDecoder, redisOperator);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public TimingUserDetailService userDetailService() {
        return new TimingUserDetailService(thirdPartyUserService);
    }

    @Bean
    public SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig(
            LoginSuccessHandler loginSuccessHandler,
            LoginFailureHandler loginFailureHandler,
            TimingUserDetailService userDetailsService) {
        return new SmsCodeAuthenticationSecurityConfig(loginFailureHandler, loginSuccessHandler, userDetailsService, stringRedisOperator);
    }

    @Bean
    public ImageCodeAuthenticationSecurityConfig imageCodeAuthenticationSecurityConfig(
            LoginSuccessHandler loginSuccessHandler,
            LoginFailureHandler loginFailureHandler,
            TimingUserDetailService userDetailsService,
            PasswordEncoder passwordEncoder) {
        return new ImageCodeAuthenticationSecurityConfig(loginFailureHandler, loginSuccessHandler, userDetailsService, passwordEncoder, stringRedisOperator);
    }

    @Bean
    public ThirdQrAuthenticationSecurityConfig weChatQrAuthenticationSecurityConfig(
            LoginSuccessHandler loginSuccessHandler,
            LoginFailureHandler loginFailureHandler,
            TimingUserDetailService userDetailsService) {
        return new ThirdQrAuthenticationSecurityConfig(loginFailureHandler, loginSuccessHandler, userDetailsService);
    }
}
